home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / TextCmd.C < prev    next >
C/C++ Source or Header  |  1992-07-06  |  14KB  |  600 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "TextCmd.h"
  6.  
  7. #include "Class.h"  
  8. #include "TextView.h" 
  9. #include "CmdNo.h"
  10. #include "StyledText.h"
  11. #include "RunArray.h"
  12. #include "Math.h"
  13.  
  14. //---- range functions ---------------------------------------------------------
  15.  
  16. void CharacterRange(Text*, int at, int *start, int *end)
  17. {
  18.     *start= *end= at;    
  19. }
  20.  
  21. void WordRange(Text *t, int at, int *start, int *end)
  22. {
  23.     t->GetWordRange(at, start, end);
  24. }
  25.  
  26. void ParagraphRange(Text *t, int at, int *start, int *end)
  27. {
  28.     t->GetParaRange(at, start, end);
  29. }
  30.  
  31. //---- RangeSelector -----------------------------------------------------------
  32.  
  33. RangeSelector::RangeSelector(class TextView *t, TextRangeFP f)
  34. {
  35.     tv= t;
  36.     range= f;
  37. }
  38.  
  39. Command *RangeSelector::TrackMouse(TrackPhase tp, Point, Point np, Point)
  40. {
  41.     SelPoint nextp;
  42.     int start, end;
  43.     
  44.     np= np-tv->GetInnerOrigin();
  45.     
  46.     switch (tp) {
  47.     case eTrackPress:
  48.     tv->DoneTyping();
  49.     tv->inTextSelector= TRUE;
  50.     tv->PointToPoint(np, &nextp.viewp, &nextp.line, &nextp.ch);
  51.     Range(tv->GetText(), nextp.ch, &start, &end);
  52.     DoPress(nextp, start, end);
  53.     break;
  54.     
  55.     case eTrackMove:
  56.     tv->PointToPoint(np, &nextp.viewp, &nextp.line, &nextp.ch);
  57.     Range(tv->GetText(), nextp.ch, &start, &end);
  58.     DoMove(nextp, start, end);
  59.     break;
  60.     
  61.     case eTrackRelease:
  62.     tv->inTextSelector= FALSE;
  63.     if ((tv->start.line == tv->end.line) && tv->Caret())
  64.         tv->InvalidateSelection();
  65.     tv->NormSelection();  
  66.     return gNoChanges;
  67.     }
  68.     return this;
  69. }
  70.  
  71. void RangeSelector::Range(Text *t, int at, int *from, int *to)
  72. {
  73.     range(t, at, from, to);
  74.     *to= Math::Min(t->End(), *to);
  75. }
  76.  
  77. void RangeSelector::DoPress(SelPoint, int s, int e)
  78. {
  79.     tv->PrivSetSelection(s, e, FALSE);
  80.     startp= tv->start;
  81.     endp= tv->end;
  82. }
  83.  
  84. void RangeSelector::DoMove(SelPoint nextp, int s, int e)
  85. {
  86.     if (nextp.ch <= startp.ch) {
  87.     tv->CharToPoint (nextp.ch= s, &nextp.line, &nextp.viewp);
  88.     if (!nextp.IsEqual(tv->start)) {
  89.         tv->InvalidateRange(nextp.line, nextp.viewp, tv->start.line, tv->start.viewp);
  90.         tv->start= nextp;
  91.     }
  92.     else if (tv->end.ch > endp.ch && !endp.IsEqual(tv->end)) {
  93.         tv->InvalidateRange(endp.line, endp.viewp, tv->end.line, tv->end.viewp);
  94.         tv->end= endp;
  95.     }            
  96.     } else {
  97.     tv->CharToPoint(nextp.ch= e, &nextp.line, &nextp.viewp);
  98.     if (!nextp.IsEqual(tv->end)) {
  99.         tv->InvalidateRange(tv->end.line, tv->end.viewp, nextp.line, nextp.viewp);
  100.         tv->end= nextp;
  101.     } 
  102.     else if (tv->start.ch < startp.ch && !startp.IsEqual(tv->start)) {
  103.         tv->InvalidateRange(tv->start.line, tv->start.viewp, startp.line, startp.viewp);
  104.         tv->start= startp;
  105.     }
  106.     }
  107. }
  108.  
  109. //---- ExtendRangeSelector ----------------------------------------------------
  110.  
  111. ExtendRangeSelector::ExtendRangeSelector(TextView *tv, TextRangeFP rf) 
  112.                             : RangeSelector(tv, rf)
  113. {
  114.     swap= FALSE;
  115. }
  116.  
  117. void ExtendRangeSelector::DoPress(SelPoint nextp, int s, int e)
  118. {
  119.     startp.ch= s;
  120.     endp.ch= e;
  121.     if (nextp.ch <= tv->start.ch) {     // extend at start 
  122.     tv->CharToPoint(startp.ch, &startp.line, &startp.viewp);
  123.     tv->InvalidateRange(startp.line, startp.viewp, tv->start.line, tv->start.viewp);
  124.     tv->start= startp;
  125.     swap= TRUE;
  126.     } else {                            // extend at end
  127.     tv->CharToPoint(endp.ch, &endp.line, &endp.viewp);
  128.     tv->InvalidateRange(tv->end.line, tv->end.viewp, endp.line, endp.viewp);
  129.     tv->end= endp;
  130.     }
  131.     startp= nextp;
  132. }
  133.  
  134. void ExtendRangeSelector::DoMove(SelPoint nextp, int s, int e)
  135. {
  136.     if (swap) {
  137.     swap= FALSE;
  138.     SwapSelPoints(tv->start, tv->end);
  139.     } 
  140.     if (nextp.ch < startp.ch)
  141.     tv->CharToPoint(nextp.ch= s, &nextp.line, &nextp.viewp);
  142.     else
  143.     tv->CharToPoint(nextp.ch= e, &nextp.line, &nextp.viewp);
  144.     
  145.     if (!nextp.IsEqual(tv->end)) {
  146.     tv->InvalidateRange(nextp.line, nextp.viewp, tv->end.line, tv->end.viewp);
  147.     tv->end= nextp;
  148.     } 
  149. }
  150.  
  151. //---- QuickPasteSelector ------------------------------------------------------
  152.  
  153. QuickPasteSelector::QuickPasteSelector(class TextView *tv, int f, int t)
  154.                                  : RangeSelector(tv)
  155.     from= f;
  156.     to= t;
  157. }
  158.  
  159. Command *QuickPasteSelector::TrackMouse(TrackPhase tp, Point ap, Point pp, Point np)
  160. {
  161.     Command *cmd= RangeSelector::TrackMouse(tp, ap, pp, np);
  162.     if (tp == eTrackRelease) {
  163.     if (tv->Caret()) {
  164.         tv->SetSelection(from, to);
  165.         return gNoChanges;
  166.     }
  167.     Text *t= tv->SelectionAsText();
  168.     tv->SetSelection(from, to);
  169.     return new PasteCommand(tv, t); 
  170.     }
  171.     return cmd;
  172. }
  173.  
  174. //---- DragAndDropSelector ---------------------------------------------------
  175.  
  176. GrCursor DragAndDropSelector::oldcursor;
  177.  
  178. DragAndDropSelector::DragAndDropSelector(class TextView *tvp, int s, int e, bool p)
  179.     dst= from= s;
  180.     to= e;
  181.     tv= tvp;
  182.     moved= FALSE;
  183.     paste= p;
  184.     t= tvp->GetText();
  185. }
  186.  
  187. Command *DragAndDropSelector::TrackMouse(TrackPhase tp, Point ap, Point, Point np)
  188. {
  189.     delta= np-ap;
  190.     switch (tp) {
  191.     case eTrackPress:
  192.     oldcursor= GrGetCursor();
  193.     break;
  194.     case eTrackMove:
  195.     if (Math::Abs(delta.x) > 4 || Math::Abs(delta.y) > 4) {
  196.         GrSetCursor(eCrsMoveHand);
  197.         moved= TRUE;
  198.     }
  199.     break;
  200.     case eTrackRelease:
  201.     GrSetCursor(oldcursor);
  202.     tv->SetSelection(dst, dst, TRUE);
  203.     if (moved && !(dst >= from && dst < to)) {
  204.         Text *txtsrc= t->Save(from, to);
  205.         tv->SetSelection(dst, dst, TRUE);
  206.         if (paste || tv->DeleteRequest(from, to) == FALSE)
  207.         return new PasteCommand(tv, txtsrc); 
  208.         return new MoveTextCommand(tv, from, to, dst);
  209.     }
  210.     return gNoChanges;
  211.     }
  212.     return this;
  213. }
  214.  
  215. void DragAndDropSelector::TrackFeedback(Point, Point np, bool)
  216. {
  217.     Point p;
  218.     int line;
  219.     np= np-tv->GetInnerOrigin();
  220.     tv->PointToPoint(np, &p, &line, &dst);
  221.     if (dst < from || dst >= to)
  222.     DrawCaretFeedback(dst);
  223. }
  224.  
  225. void DragAndDropSelector::DrawCaretFeedback(int at)
  226. {
  227.     int l;
  228.     Point p;
  229.     tv->CharToPoint(at, &l, &p);
  230.     p+= tv->GetInnerOrigin();
  231.     int bh= tv->BaseHeight(l);
  232.     
  233.     GrSetInk(gInkXor);
  234.     GrMoveto(p);
  235.     GrLineto(Point(p.x, p.y+bh));
  236. }
  237.  
  238. //----- TextCommand Methods ----------------------------------------------------
  239.  
  240. NewAbstractMetaImpl(TextCommand, Command, (TP(tv), TP(oldText), T(oldStart), T(oldEnd)));
  241.  
  242. TextCommand::TextCommand (TextView *t, int cmdNo, char *cmdName, bool save)
  243.                             : Command(cmdNo, cmdName)
  244. {
  245.     tv= t;
  246.     tv->GetSelection(&oldStart, &oldEnd);
  247.     oldText= (Text*)tv->GetText()->New();
  248.     if (save && oldStart != oldEnd) // save old text
  249.     tv->Copy(oldText);
  250. }
  251.  
  252. TextCommand::~TextCommand ()
  253. {
  254.     SafeDelete(oldText);
  255.  
  256. void TextCommand::RestoreSelection ()
  257. {
  258.     tv->SetSelection(oldStart, oldEnd, FALSE);
  259. }
  260.  
  261. void TextCommand::RedoIt()
  262. {
  263.     RestoreSelection();
  264.     DoIt();
  265.     tv->RevealSelection();
  266. }
  267.  
  268. //----- CutCopyCommand Methods -------------------------------------------------
  269.  
  270. NewMetaImpl0(CutCopyCommand, TextCommand);
  271.  
  272. CutCopyCommand::CutCopyCommand(TextView *t, int cmdNo, char *cmdName) 
  273.                 : TextCommand(t, cmdNo, 0, cmdNo != cCOPY)
  274.     if (cmdName == 0) {
  275.     if (cmdNo == cCUT)
  276.         cmdName= "Cut Text";
  277.     else if (cmdNo == cCOPY) 
  278.         cmdName= "Copy Text";
  279.     }
  280.     SetName(cmdName);
  281.     if (cmdNo == cCOPY)
  282.     SetType(eCmdTypeNoChange);
  283. }
  284.  
  285. void CutCopyCommand::DoIt()
  286. {
  287.     if (GetId() == cCOPY)
  288.     return;
  289.     tv->Cut();
  290.     tv->RevealSelection();
  291. }  
  292.  
  293. void CutCopyCommand::UndoIt()
  294. {
  295.     Text *t= tv->GetText();    
  296.  
  297.     if (GetId() == cCUT) {
  298.     tv->SetSelection(oldStart, oldStart, FALSE);
  299.     if (oldText->End() != 0) 
  300.         tv->Paste(oldText);
  301.     RestoreSelection();
  302.     tv->RevealSelection();
  303.     }
  304. }
  305.  
  306. //----- Paste Command Methods --------------------------------------------------
  307.  
  308. NewMetaImpl(PasteCommand, TextCommand, (TP(pastetext), T(newStart), T(newEnd)));
  309.  
  310. PasteCommand::PasteCommand(TextView *t, Text *pt, int cmdNo, char *cmdName) 
  311.             : TextCommand(t, cmdNo, cmdName ? cmdName : "Paste Text")
  312. {
  313.     pastetext= pt;
  314. }
  315.  
  316. PasteCommand::~PasteCommand()
  317. {
  318.     SafeDelete(pastetext);
  319. }
  320.  
  321. void PasteCommand::DoIt()
  322. {
  323.     tv->Paste(pastetext);
  324.     tv->GetSelection(&newStart, &newEnd);
  325.     tv->RevealSelection();
  326. }  
  327.  
  328. void PasteCommand::UndoIt()
  329. {
  330.     tv->SetSelection(oldStart, newEnd, FALSE);
  331.     tv->Cut();
  332.     if (oldText->End() != 0)
  333.     tv->Paste(oldText);
  334.     RestoreSelection();
  335.     tv->RevealSelection();
  336. }
  337.  
  338. //---- MoveTextCommand -------------------------------------------------------
  339.  
  340. MoveTextCommand::MoveTextCommand(TextView *tview, int f, int t, int d) 
  341.                         : Command(cPASTE, "Move Text")
  342. {
  343.     tv= tview;
  344.     from= f;
  345.     to= t;
  346.     dst= d;
  347.     mt= 0;
  348. }
  349.  
  350. MoveTextCommand::~MoveTextCommand()
  351. {
  352.     SafeDelete(mt);
  353. }
  354.  
  355. void MoveTextCommand::DoIt()
  356. {
  357.     int nd= dst;
  358.     if (dst > from)
  359.     nd= nd-(to-from);
  360.     if (!mt)
  361.     mt= tv->GetText()->Save(from, to);
  362.     tv->SetSelection(from, to, FALSE);
  363.     tv->Cut();
  364.     tv->SetSelection(nd, nd, FALSE);
  365.     tv->Paste(mt);
  366.     tv->SetSelection(nd, nd+to-from, FALSE);
  367.     tv->RevealSelection();
  368. }  
  369.  
  370. void MoveTextCommand::UndoIt()
  371. {
  372.     int nd= dst;
  373.     if (dst > from)
  374.     nd= nd-(to-from);
  375.     tv->SetSelection(nd, nd+to-from, FALSE);
  376.     tv->Cut();
  377.     tv->SetSelection(from, from, FALSE);
  378.     tv->Paste(mt);
  379.     tv->SetSelection(from, to, FALSE);
  380.     tv->RevealSelection();
  381. }
  382.  
  383. //----- TypeInCommand Command Methods ------------------------------------------
  384.  
  385. NewMetaImpl(TypingCommand, TextCommand, 
  386.                    (TP(backspaceBuf), TP(newText), T(newStart)));
  387.  
  388. TypingCommand::TypingCommand(TextView *t, int cmdNo, char *cmdName) 
  389.                            : TextCommand(t, cmdNo, cmdName) 
  390. {
  391.     Text *txt= tv->GetText();
  392.     backspaceBuf= (Text*) txt->New();
  393.     newText= (Text*) txt->New();
  394.     newStart= oldStart;
  395. }
  396.  
  397. TypingCommand::~TypingCommand()
  398. {
  399.     tv->TypingDeleted(this);
  400.     SafeDelete(backspaceBuf);
  401.     SafeDelete(newText);
  402. }
  403.  
  404. void TypingCommand::UndoIt()
  405. {
  406.     Text *t= tv->GetText();
  407.     int firstNewChar;
  408.  
  409.     firstNewChar= Math::Min(oldStart - backspaceBuf->End(), oldStart);
  410.     if (firstNewChar != newStart) {                     // save new text
  411.     t->Copy(newText, firstNewChar, newStart);         
  412.     tv->SetSelection(firstNewChar, newStart, TRUE);
  413.     tv->Cut();                                      // remove new text
  414.     } else
  415.     tv->SetSelection(firstNewChar, newStart, TRUE);
  416.     if (backspaceBuf->End() != 0)                            
  417.     tv->Paste(backspaceBuf);                        // insert saved text
  418.     if (oldText->End() != 0)
  419.     tv->Paste(oldText);
  420.     RestoreSelection();
  421.     tv->RevealSelection();
  422. }
  423.  
  424. void TypingCommand::RedoIt()
  425. {
  426.     RestoreSelection();
  427.     tv->Cut();
  428.     if (backspaceBuf->End() != 0) {
  429.     tv->SetSelection(oldStart - backspaceBuf->End(), oldStart, FALSE);
  430.     tv->Cut();        
  431.     }
  432.     if (newText->End() != 0)
  433.     tv->Paste(newText);
  434.     tv->RevealSelection();
  435. }
  436.  
  437. void TypingCommand::AddChar(int n)
  438.     newStart+= n; 
  439. }
  440.  
  441. void TypingCommand::DelChar()
  442. {
  443.     Text *t= tv->GetText();
  444.  
  445.     if (newStart > 0)
  446.     newStart--;  
  447.     if (newStart < oldStart) 
  448.     if (oldStart - newStart > backspaceBuf->End()) { // char already saved??
  449.         backspaceBuf->ReplaceRange(0, 0, t, newStart, newStart+1);
  450.     }
  451. }
  452.  
  453. //---- class CharStyleCommand -------------------------------------------------------
  454.  
  455. NewMetaImpl(CharStyleCommand, TextCommand, (TP(newStyles), TP(oldStyles), TP(tvp), TE(mode)));
  456.  
  457. CharStyleCommand::CharStyleCommand(TextView *t, int cmdNo, char *cmdName, 
  458.        TxtCharProp m, const CharStyleSpec &ns) 
  459.                     : TextCommand(t, cmdNo, cmdName, FALSE)
  460. {
  461.     st= Guard(t->GetText(), StyledText);
  462.     newStyles= oldStyles= 0;
  463.     tvp= t; 
  464.     style= ns;
  465.     mode= m;
  466. }
  467.  
  468. CharStyleCommand::~CharStyleCommand()
  469. {
  470.     SafeDelete(oldStyles);
  471.     SafeDelete(newStyles);
  472. }
  473.  
  474. void CharStyleCommand::DoIt()
  475. {
  476.     int from, to;
  477.  
  478.     tvp->GetSelection(&from, &to);
  479.     if (tvp->Caret())
  480.     st->SetCharStyle(mode, from, to, style);
  481.     else {    
  482.     if (oldStyles == 0) 
  483.         oldStyles= new RunArray;
  484.     st->GetCharStyles()->Copy(oldStyles, from, to);
  485.     st->SetCharStyle(mode, from, to, style);
  486.     }
  487.     tvp->RevealSelection();
  488. }  
  489.  
  490. void CharStyleCommand::UndoIt()
  491. {
  492.     if (oldStart == oldEnd)
  493.     st->ResetCurrentCharStyle();
  494.     else {
  495.     if (newStyles == 0) {
  496.         newStyles= new RunArray;
  497.         st->GetCharStyles()->Copy(newStyles, oldStart, oldEnd);
  498.     }
  499.     st->ReplaceCharStyles(oldStyles, oldStart, oldEnd); 
  500.     }
  501.     RestoreSelection();
  502.     tvp->RevealSelection();
  503. }
  504.  
  505. void CharStyleCommand::RedoIt()
  506. {
  507.     if (oldStart == oldEnd)
  508.     st->SetCharStyle(mode, oldStart, oldEnd, style);        
  509.     else
  510.     st->ReplaceCharStyles(newStyles, oldStart, oldEnd); 
  511.     RestoreSelection();
  512.     tvp->RevealSelection();
  513. }
  514.  
  515.  
  516. //---- class ParaStyleCommand -------------------------------------------------------
  517.  
  518. NewMetaImpl(ParaStyleCommand, TextCommand, (TP(newStyles), TP(oldStyles), TP(tvp)));
  519.  
  520. ParaStyleCommand::ParaStyleCommand(
  521.     TextView *t, int cmdNo, char *cmdName, TxtParaProp p, const ParaDesc &newStyle
  522. ): TextCommand(t, cmdNo, cmdName, FALSE)
  523. {
  524.     st= Guard(t->GetText(), StyledText);
  525.     newStyles= oldStyles= 0;
  526.     tvp= t; 
  527.     mode= p;
  528.     style= newStyle;
  529.     notify= 0;
  530. }
  531.  
  532. ParaStyleCommand::~ParaStyleCommand()
  533. {
  534.     SafeDelete(oldStyles);
  535.     SafeDelete(newStyles);
  536.     if (notify)
  537.     notify->Control(cIdNone, cPartCommandDone, this);
  538. }
  539.  
  540. void ParaStyleCommand::DoIt()
  541. {
  542.     int from, to, dd;
  543.  
  544.     tvp->GetSelection(&from, &to);
  545.     st->GetParaRange(from, &oldStart, &dd);
  546.     if (to == from)
  547.     oldEnd= dd;
  548.     else if (st->IsPara((*st)[to-1]))
  549.     oldEnd= to;
  550.     else
  551.     st->GetParaRange(to, &dd, &oldEnd);
  552.     if (oldStyles == 0) {
  553.     oldStyles= new RunArray; 
  554.     st->GetParaStyles()->Copy(oldStyles, oldStart, oldEnd);
  555.     }
  556.     st->SetParaStyle(mode, oldStart, oldEnd, style);
  557.     tvp->RevealSelection();
  558. }  
  559.  
  560. void ParaStyleCommand::UndoIt()
  561. {
  562.     if (newStyles == 0) {
  563.     newStyles= new RunArray;
  564.     st->GetParaStyles()->Copy(newStyles, oldStart, oldEnd);
  565.     }
  566.     st->ReplaceParaStyles(oldStyles, oldStart, oldEnd); 
  567.     RestoreSelection();
  568.     tvp->RevealSelection();
  569. }
  570.  
  571. void ParaStyleCommand::RedoIt()
  572. {
  573.     st->ReplaceParaStyles(newStyles, oldStart, oldEnd); 
  574.     RestoreSelection();
  575.     tvp->RevealSelection();
  576. }
  577.  
  578. void ParaStyleCommand::Apply(TxtParaProp p, const ParaDesc &newStyle)
  579. {
  580.     mode= p;
  581.     style= newStyle;
  582. }
  583.  
  584. void ParaStyleCommand::NotifyWhenDone(EvtHandler *evt)
  585. {
  586.     notify= evt;
  587. }
  588.  
  589. TxtParaProp ParaStyleCommand::GetNewStyle(ParaDesc &newStyle)
  590. {
  591.     newStyle= style;
  592.     return mode;    
  593. }
  594.  
  595.